﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using Hardcodet.Wpf.TaskbarNotification.Interop;

namespace Hardcodet.Wpf.TaskbarNotification
{
	/// <summary>
	/// Contains declarations of WPF dependency properties
	/// and events.
	/// </summary>
	partial class TaskbarIcon
	{
		/// <summary>
		/// Category name that is set on designer properties.
		/// </summary>
		public const string CategoryName = "NotifyIcon";

		#region TrayPopupResolved

		/// <summary>
		/// TrayPopupResolved Read-Only Dependency Property
		/// </summary>
		static private readonly DependencyPropertyKey TrayPopupResolvedPropertyKey =
			DependencyProperty.RegisterReadOnly("TrayPopupResolved",
			                                    typeof(Popup),
			                                    typeof(TaskbarIcon),
			                                    new FrameworkPropertyMetadata(null));

		/// <summary>
		/// A read-only dependency property that returns the <see cref="Popup"/>
		/// that is being displayed in the taskbar area based on a user action.
		/// </summary>
		static public readonly DependencyProperty TrayPopupResolvedProperty = TrayPopupResolvedPropertyKey.DependencyProperty;

		/// <summary>
		/// Gets the TrayPopupResolved property. Returns
		/// a <see cref="Popup"/> which is either the
		/// <see cref="TrayPopup"/> control itself or a
		/// <see cref="Popup"/> control that contains the
		/// <see cref="TrayPopup"/>.
		/// </summary>
		[Category(CategoryName)]
		public Popup TrayPopupResolved
		{
			get { return (Popup)this.GetValue(TrayPopupResolvedProperty); }
		}

		/// <summary>
		/// Provides a secure method for setting the TrayPopupResolved property.  
		/// This dependency property indicates ....
		/// </summary>
		/// <param name="value">The new value for the property.</param>
		protected void SetTrayPopupResolved(Popup value)
		{
			this.SetValue(TrayPopupResolvedPropertyKey, value);
		}

		#endregion

		#region TrayToolTipResolved

		/// <summary>
		/// TrayToolTipResolved Read-Only Dependency Property
		/// </summary>
		static private readonly DependencyPropertyKey TrayToolTipResolvedPropertyKey =
			DependencyProperty.RegisterReadOnly("TrayToolTipResolved",
			                                    typeof(ToolTip),
			                                    typeof(TaskbarIcon),
			                                    new FrameworkPropertyMetadata(null));

		/// <summary>
		/// A read-only dependency property that returns the <see cref="ToolTip"/>
		/// that is being displayed.
		/// </summary>
		static public readonly DependencyProperty TrayToolTipResolvedProperty =
			TrayToolTipResolvedPropertyKey.DependencyProperty;

		/// <summary>
		/// Gets the TrayToolTipResolved property. Returns 
		/// a <see cref="ToolTip"/> control that was created
		/// in order to display either <see cref="TrayToolTip"/>
		/// or <see cref="ToolTipText"/>.
		/// </summary>
		[Category(CategoryName)]
		[Browsable(true)]
		[Bindable(true)]
		public ToolTip TrayToolTipResolved
		{
			get { return (ToolTip)this.GetValue(TrayToolTipResolvedProperty); }
		}

		/// <summary>
		/// Provides a secure method for setting the <see cref="TrayToolTipResolved"/>
		/// property.  
		/// </summary>
		/// <param name="value">The new value for the property.</param>
		protected void SetTrayToolTipResolved(ToolTip value)
		{
			this.SetValue(TrayToolTipResolvedPropertyKey, value);
		}

		#endregion

		#region CustomBalloon

		/// <summary>
		/// CustomBalloon Read-Only Dependency Property
		/// </summary>
		static private readonly DependencyPropertyKey CustomBalloonPropertyKey =
			DependencyProperty.RegisterReadOnly("CustomBalloon",
			                                    typeof(Popup),
			                                    typeof(TaskbarIcon),
			                                    new FrameworkPropertyMetadata(null));

		/// <summary>
		/// 
		/// </summary>
		static public readonly DependencyProperty CustomBalloonProperty = CustomBalloonPropertyKey.DependencyProperty;

		/// <summary>
		/// A custom popup that is being displayed in the tray area in order
		/// to display messages to the user.
		/// </summary>
		public Popup CustomBalloon
		{
			get { return (Popup)this.GetValue(CustomBalloonProperty); }
		}

		/// <summary>
		/// Provides a secure method for setting the <see cref="CustomBalloon"/> property.  
		/// </summary>
		/// <param name="value">The new value for the property.</param>
		protected void SetCustomBalloon(Popup value)
		{
			this.SetValue(CustomBalloonPropertyKey, value);
		}

		#endregion

		#region Icon property / IconSource dependency property

		/// <summary>
		/// Resolves an image source and updates the <see cref="Icon" /> property accordingly.
		/// </summary>
		static public readonly DependencyProperty IconSourceProperty = DependencyProperty.Register("IconSource",
		                                                                                           typeof(ImageSource),
		                                                                                           typeof(TaskbarIcon),
		                                                                                           new FrameworkPropertyMetadata
		                                                                                           	(null,
		                                                                                           	 IconSourcePropertyChanged));

		/// <summary>
		/// 
		/// </summary>
		private Icon _icon;

		/// <summary>
		/// Gets or sets the icon to be displayed. This is not a
		/// dependency property - if you want to assign the property
		/// through XAML, please use the <see cref="IconSource"/>
		/// dependency property.
		/// </summary>
		[Browsable(false)]
		public Icon Icon
		{
			get { return this._icon; }
			set
			{
				this._icon = value;
				this._iconData.IconHandle = value == null ? IntPtr.Zero : this._icon.Handle;

				Util.WriteIconData(ref this._iconData, NotifyCommand.Modify, IconDataMembers.Icon);
			}
		}

		/// <summary>
		/// A property wrapper for the <see cref="IconSourceProperty"/>
		/// dependency property:<br/>
		/// Resolves an image source and updates the <see cref="Icon" /> property accordingly.
		/// </summary>
		[Category(CategoryName)]
		[Description("Sets the displayed taskbar icon.")]
		public ImageSource IconSource
		{
			get { return (ImageSource)this.GetValue(IconSourceProperty); }
			set { this.SetValue(IconSourceProperty, value); }
		}

		/// <summary>
		/// A static callback listener which is being invoked if the
		/// <see cref="IconSourceProperty"/> dependency property has
		/// been changed. Invokes the <see cref="OnIconSourcePropertyChanged"/>
		/// instance method of the changed instance.
		/// </summary>
		/// <param name="d">The currently processed owner of the property.</param>
		/// <param name="e">Provides information about the updated property.</param>
		static private void IconSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TaskbarIcon owner = (TaskbarIcon)d;
			owner.OnIconSourcePropertyChanged(e);
		}

		/// <summary>
		/// Handles changes of the <see cref="IconSourceProperty"/> dependency property. As
		/// WPF internally uses the dependency property system and bypasses the
		/// <see cref="IconSource"/> property wrapper, updates of the property's value
		/// should be handled here.
		/// </summary>
		/// <param name="e">Provides information about the updated property.</param>
		private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			ImageSource newValue = (ImageSource)e.NewValue;

			//resolving the ImageSource at design time is unlikely to work
			if (!Util.IsDesignMode)
				this.Icon = newValue.ToIcon();
		}

		#endregion

		#region ToolTipText dependency property

		/// <summary>
		/// A tooltip text that is being displayed if no custom <see cref="ToolTip"/>
		/// was set or if custom tooltips are not supported.
		/// </summary>
		static public readonly DependencyProperty ToolTipTextProperty = DependencyProperty.Register("ToolTipText",
		                                                                                            typeof(string),
		                                                                                            typeof(TaskbarIcon),
		                                                                                            new FrameworkPropertyMetadata
		                                                                                            	(String.Empty,
		                                                                                            	 ToolTipTextPropertyChanged));

		/// <summary>
		/// A property wrapper for the <see cref="ToolTipTextProperty"/>
		/// dependency property:<br/>
		/// A tooltip text that is being displayed if no custom <see cref="ToolTip"/>
		/// was set or if custom tooltips are not supported.
		/// </summary>
		[Category(CategoryName)]
		[Description("Alternative to a fully blown ToolTip, which is only displayed on Vista and above.")]
		public string ToolTipText
		{
			get { return (string)this.GetValue(ToolTipTextProperty); }
			set { this.SetValue(ToolTipTextProperty, value); }
		}

		/// <summary>
		/// A static callback listener which is being invoked if the
		/// <see cref="ToolTipTextProperty"/> dependency property has
		/// been changed. Invokes the <see cref="OnToolTipTextPropertyChanged"/>
		/// instance method of the changed instance.
		/// </summary>
		/// <param name="d">The currently processed owner of the property.</param>
		/// <param name="e">Provides information about the updated property.</param>
		static private void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TaskbarIcon owner = (TaskbarIcon)d;
			owner.OnToolTipTextPropertyChanged(e);
		}

		/// <summary>
		/// Handles changes of the <see cref="ToolTipTextProperty"/> dependency property. As
		/// WPF internally uses the dependency property system and bypasses the
		/// <see cref="ToolTipText"/> property wrapper, updates of the property's value
		/// should be handled here.
		/// </summary>
		/// <param name="e">Provides information about the updated property.</param>
		private void OnToolTipTextPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			//only recreate tooltip if we're not using a custom control
			if (this.TrayToolTipResolved == null || this.TrayToolTipResolved.Content is string)
				this.CreateCustomToolTip();

			this.WriteToolTipSettings();
		}

		#endregion

		#region TrayToolTip dependency property

		/// <summary>
		/// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon.
		/// Works only with Vista and above. Accordingly, you should make sure that
		/// the <see cref="ToolTipText"/> property is set as well.
		/// </summary>
		static public readonly DependencyProperty TrayToolTipProperty = DependencyProperty.Register("TrayToolTip",
		                                                                                            typeof(UIElement),
		                                                                                            typeof(TaskbarIcon),
		                                                                                            new FrameworkPropertyMetadata
		                                                                                            	(null,
		                                                                                            	 TrayToolTipPropertyChanged));

		/// <summary>
		/// A property wrapper for the <see cref="TrayToolTipProperty"/>
		/// dependency property:<br/>
		/// A custom UI element that is displayed as a tooltip if the user hovers over the taskbar icon.
		/// Works only with Vista and above. Accordingly, you should make sure that
		/// the <see cref="ToolTipText"/> property is set as well.
		/// </summary>
		[Category(CategoryName)]
		[Description("Custom UI element that is displayed as a tooltip. Only on Vista and above")]
		public UIElement TrayToolTip
		{
			get { return (UIElement)this.GetValue(TrayToolTipProperty); }
			set { this.SetValue(TrayToolTipProperty, value); }
		}

		/// <summary>
		/// A static callback listener which is being invoked if the
		/// <see cref="TrayToolTipProperty"/> dependency property has
		/// been changed. Invokes the <see cref="OnTrayToolTipPropertyChanged"/>
		/// instance method of the changed instance.
		/// </summary>
		/// <param name="d">The currently processed owner of the property.</param>
		/// <param name="e">Provides information about the updated property.</param>
		static private void TrayToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TaskbarIcon owner = (TaskbarIcon)d;
			owner.OnTrayToolTipPropertyChanged(e);
		}

		/// <summary>
		/// Handles changes of the <see cref="TrayToolTipProperty"/> dependency property. As
		/// WPF internally uses the dependency property system and bypasses the
		/// <see cref="TrayToolTip"/> property wrapper, updates of the property's value
		/// should be handled here.
		/// </summary>
		/// <param name="e">Provides information about the updated property.</param>
		private void OnTrayToolTipPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			//recreate tooltip control
			this.CreateCustomToolTip();

			if (e.OldValue != null)
			{
				//remove the taskbar icon reference from the previously used element
				SetParentTaskbarIcon((DependencyObject)e.OldValue, null);
			}

			if (e.NewValue != null)
			{
				//set this taskbar icon as a reference to the new tooltip element
				SetParentTaskbarIcon((DependencyObject)e.NewValue, this);
			}

			//update tooltip settings - needed to make sure a string is set, even
			//if the ToolTipText property is not set. Otherwise, the event that
			//triggers tooltip display is never fired.
			this.WriteToolTipSettings();
		}

		#endregion

		#region TrayPopup dependency property

		/// <summary>
		/// A control that is displayed as a popup when the taskbar icon is clicked.
		/// </summary>
		static public readonly DependencyProperty TrayPopupProperty = DependencyProperty.Register("TrayPopup",
		                                                                                          typeof(UIElement),
		                                                                                          typeof(TaskbarIcon),
		                                                                                          new FrameworkPropertyMetadata
		                                                                                          	(null,
		                                                                                          	 TrayPopupPropertyChanged));

		/// <summary>
		/// A property wrapper for the <see cref="TrayPopupProperty"/>
		/// dependency property:<br/>
		/// A control that is displayed as a popup when the taskbar icon is clicked.
		/// </summary>
		[Category(CategoryName)]
		[Description("Displayed as a Popup if the user clicks on the taskbar icon.")]
		public UIElement TrayPopup
		{
			get { return (UIElement)this.GetValue(TrayPopupProperty); }
			set { this.SetValue(TrayPopupProperty, value); }
		}

		/// <summary>
		/// A static callback listener which is being invoked if the
		/// <see cref="TrayPopupProperty"/> dependency property has
		/// been changed. Invokes the <see cref="OnTrayPopupPropertyChanged"/>
		/// instance method of the changed instance.
		/// </summary>
		/// <param name="d">The currently processed owner of the property.</param>
		/// <param name="e">Provides information about the updated property.</param>
		static private void TrayPopupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TaskbarIcon owner = (TaskbarIcon)d;
			owner.OnTrayPopupPropertyChanged(e);
		}

		/// <summary>
		/// Handles changes of the <see cref="TrayPopupProperty"/> dependency property. As
		/// WPF internally uses the dependency property system and bypasses the
		/// <see cref="TrayPopup"/> property wrapper, updates of the property's value
		/// should be handled here.
		/// </summary>
		/// <param name="e">Provides information about the updated property.</param>
		private void OnTrayPopupPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			if (e.OldValue != null)
			{
				//remove the taskbar icon reference from the previously used element
				SetParentTaskbarIcon((DependencyObject)e.OldValue, null);
			}

			if (e.NewValue != null)
			{
				//set this taskbar icon as a reference to the new tooltip element
				SetParentTaskbarIcon((DependencyObject)e.NewValue, this);
			}

			//create a pop
			this.CreatePopup();
		}

		#endregion

		#region MenuActivation dependency property

		/// <summary>
		/// Defines what mouse events display the context menu.
		/// Defaults to <see cref="PopupActivationMode.RightClick"/>.
		/// </summary>
		static public readonly DependencyProperty MenuActivationProperty = DependencyProperty.Register("MenuActivation",
		                                                                                               typeof(
		                                                                                               	PopupActivationMode),
		                                                                                               typeof(TaskbarIcon),
		                                                                                               new FrameworkPropertyMetadata
		                                                                                               	(PopupActivationMode.
		                                                                                               	 	RightClick));

		/// <summary>
		/// A property wrapper for the <see cref="MenuActivationProperty"/>
		/// dependency property:<br/>
		/// Defines what mouse events display the context menu.
		/// Defaults to <see cref="PopupActivationMode.RightClick"/>.
		/// </summary>
		[Category(CategoryName)]
		[Description("Defines what mouse events display the context menu.")]
		public PopupActivationMode MenuActivation
		{
			get { return (PopupActivationMode)this.GetValue(MenuActivationProperty); }
			set { this.SetValue(MenuActivationProperty, value); }
		}

		#endregion

		#region PopupActivation dependency property

		/// <summary>
		/// Defines what mouse events trigger the <see cref="TrayPopup" />.
		/// Default is <see cref="PopupActivationMode.LeftClick" />.
		/// </summary>
		static public readonly DependencyProperty PopupActivationProperty = DependencyProperty.Register("PopupActivation",
		                                                                                                typeof(
		                                                                                                	PopupActivationMode),
		                                                                                                typeof(TaskbarIcon),
		                                                                                                new FrameworkPropertyMetadata
		                                                                                                	(PopupActivationMode.
		                                                                                                	 	LeftClick));

		/// <summary>
		/// A property wrapper for the <see cref="PopupActivationProperty"/>
		/// dependency property:<br/>
		/// Defines what mouse events trigger the <see cref="TrayPopup" />.
		/// Default is <see cref="PopupActivationMode.LeftClick" />.
		/// </summary>
		[Category(CategoryName)]
		[Description("Defines what mouse events display the TaskbarIconPopup.")]
		public PopupActivationMode PopupActivation
		{
			get { return (PopupActivationMode)this.GetValue(PopupActivationProperty); }
			set { this.SetValue(PopupActivationProperty, value); }
		}

		#endregion

		#region Visibility dependency property override

		/// <summary>
		/// A static callback listener which is being invoked if the
		/// <see cref="UIElement.VisibilityProperty"/> dependency property has
		/// been changed. Invokes the <see cref="OnVisibilityPropertyChanged"/>
		/// instance method of the changed instance.
		/// </summary>
		/// <param name="d">The currently processed owner of the property.</param>
		/// <param name="e">Provides information about the updated property.</param>
		static private void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TaskbarIcon owner = (TaskbarIcon)d;
			owner.OnVisibilityPropertyChanged(e);
		}

		/// <summary>
		/// Handles changes of the <see cref="UIElement.VisibilityProperty"/> dependency property. As
		/// WPF internally uses the dependency property system and bypasses the
		/// <see cref="Visibility"/> property wrapper, updates of the property's value
		/// should be handled here.
		/// </summary>
		/// <param name="e">Provides information about the updated property.</param>
		private void OnVisibilityPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			Visibility newValue = (Visibility)e.NewValue;

			//update
			if (newValue == Visibility.Visible)
				this.CreateTaskbarIcon();
			else
				this.RemoveTaskbarIcon();
		}

		#endregion

		#region DataContext dependency property override / target update

		/// <summary>
		/// Updates the <see cref="FrameworkElement.DataContextProperty"/> of a given
		/// <see cref="FrameworkElement"/>. This method only updates target elements
		/// that do not already have a data context of their own, and either assigns
		/// the <see cref="FrameworkElement.DataContext"/> of the NotifyIcon, or the
		/// NotifyIcon itself, if no data context was assigned at all.
		/// </summary>
		private void UpdateDataContext(FrameworkElement target, object oldDataContextValue, object newDataContextValue)
		{
			//if there is no target or it's data context is determined through a binding
			//of its own, keep it
			if (target == null || target.IsDataContextDataBound())
				return;

			//if the target's data context is the NotifyIcon's old DataContext or the NotifyIcon itself,
			//update it
			if (ReferenceEquals(this, target.DataContext) || Equals(oldDataContextValue, target.DataContext))
			{
				//assign own data context, if available. If there is no data
				//context at all, assign NotifyIcon itself.
				target.DataContext = newDataContextValue ?? this;
			}
		}

		/// <summary>
		/// A static callback listener which is being invoked if the
		/// <see cref="FrameworkElement.DataContextProperty"/> dependency property has
		/// been changed. Invokes the <see cref="OnDataContextPropertyChanged"/>
		/// instance method of the changed instance.
		/// </summary>
		/// <param name="d">The currently processed owner of the property.</param>
		/// <param name="e">Provides information about the updated property.</param>
		static private void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TaskbarIcon owner = (TaskbarIcon)d;
			owner.OnDataContextPropertyChanged(e);
		}

		/// <summary>
		/// Handles changes of the <see cref="FrameworkElement.DataContextProperty"/> dependency property. As
		/// WPF internally uses the dependency property system and bypasses the
		/// <see cref="FrameworkElement.DataContext"/> property wrapper, updates of the property's value
		/// should be handled here.
		/// </summary>
		/// <param name="e">Provides information about the updated property.</param>
		private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			object newValue = e.NewValue;
			object oldValue = e.OldValue;

			//replace custom data context for ToolTips, Popup, and
			//ContextMenu
			this.UpdateDataContext(this.TrayPopupResolved, oldValue, newValue);
			this.UpdateDataContext(this.TrayToolTipResolved, oldValue, newValue);
			this.UpdateDataContext(this.ContextMenu, oldValue, newValue);
		}

		#endregion

		#region ContextMenu dependency property override

		/// <summary>
		/// A static callback listener which is being invoked if the
		/// <see cref="FrameworkElement.ContextMenuProperty"/> dependency property has
		/// been changed. Invokes the <see cref="OnContextMenuPropertyChanged"/>
		/// instance method of the changed instance.
		/// </summary>
		/// <param name="d">The currently processed owner of the property.</param>
		/// <param name="e">Provides information about the updated property.</param>
		static private void ContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TaskbarIcon owner = (TaskbarIcon)d;
			owner.OnContextMenuPropertyChanged(e);
		}

		/// <summary>
		/// Releases the old and updates the new <see cref="ContextMenu"/> property
		/// in order to reflect both the NotifyIcon's <see cref="FrameworkElement.DataContext"/>
		/// property and have the <see cref="ParentTaskbarIconProperty"/> assigned.
		/// </summary>
		/// <param name="e">Provides information about the updated property.</param>
		private void OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			if (e.OldValue != null)
			{
				//remove the taskbar icon reference from the previously used element
				SetParentTaskbarIcon((DependencyObject)e.OldValue, null);
			}

			if (e.NewValue != null)
			{
				//set this taskbar icon as a reference to the new tooltip element
				SetParentTaskbarIcon((DependencyObject)e.NewValue, this);
			}

			this.UpdateDataContext((ContextMenu)e.NewValue, null, this.DataContext);
		}

		#endregion

		#region DoubleClickCommand dependency property

		/// <summary>
		/// Associates a command that is being executed if the tray icon is being
		/// double clicked.
		/// </summary>
		static public readonly DependencyProperty DoubleClickCommandProperty =
			DependencyProperty.Register("DoubleClickCommand",
			                            typeof(ICommand),
			                            typeof(TaskbarIcon),
			                            new FrameworkPropertyMetadata(null));

		/// <summary>
		/// A property wrapper for the <see cref="DoubleClickCommandProperty"/>
		/// dependency property:<br/>
		/// Associates a command that is being executed if the tray icon is being
		/// double clicked.
		/// </summary>
		public ICommand DoubleClickCommand
		{
			get { return (ICommand)this.GetValue(DoubleClickCommandProperty); }
			set { this.SetValue(DoubleClickCommandProperty, value); }
		}

		#endregion

		#region DoubleClickCommandParameter dependency property

		/// <summary>
		/// Command parameter for the <see cref="DoubleClickCommand"/>.
		/// </summary>
		static public readonly DependencyProperty DoubleClickCommandParameterProperty =
			DependencyProperty.Register("DoubleClickCommandParameter",
			                            typeof(object),
			                            typeof(TaskbarIcon),
			                            new FrameworkPropertyMetadata(null));

		/// <summary>
		/// A property wrapper for the <see cref="DoubleClickCommandParameterProperty"/>
		/// dependency property:<br/>
		/// Command parameter for the <see cref="DoubleClickCommand"/>.
		/// </summary>
		public object DoubleClickCommandParameter
		{
			get { return this.GetValue(DoubleClickCommandParameterProperty); }
			set { this.SetValue(DoubleClickCommandParameterProperty, value); }
		}

		#endregion

		#region DoubleClickCommandTarget dependency property

		/// <summary>
		/// The target of the command that is fired if the notify icon is double clicked.
		/// </summary>
		static public readonly DependencyProperty DoubleClickCommandTargetProperty =
			DependencyProperty.Register("DoubleClickCommandTarget",
			                            typeof(IInputElement),
			                            typeof(TaskbarIcon),
			                            new FrameworkPropertyMetadata(null));

		/// <summary>
		/// A property wrapper for the <see cref="DoubleClickCommandTargetProperty"/>
		/// dependency property:<br/>
		/// The target of the command that is fired if the notify icon is double clicked.
		/// </summary>
		public IInputElement DoubleClickCommandTarget
		{
			get { return (IInputElement)this.GetValue(DoubleClickCommandTargetProperty); }
			set { this.SetValue(DoubleClickCommandTargetProperty, value); }
		}

		#endregion

		#region LeftClickCommand dependency property

		/// <summary>
		/// Associates a command that is being executed if the tray icon is being
		/// double clicked.
		/// </summary>
		static public readonly DependencyProperty LeftClickCommandProperty = DependencyProperty.Register("LeftClickCommand",
		                                                                                                 typeof(ICommand),
		                                                                                                 typeof(TaskbarIcon),
		                                                                                                 new FrameworkPropertyMetadata
		                                                                                                 	(null));

		/// <summary>
		/// A property wrapper for the <see cref="LeftClickCommandProperty"/>
		/// dependency property:<br/>
		/// Associates a command that is being executed if the tray icon is being
		/// double clicked.
		/// </summary>
		public ICommand LeftClickCommand
		{
			get { return (ICommand)this.GetValue(LeftClickCommandProperty); }
			set { this.SetValue(LeftClickCommandProperty, value); }
		}

		#endregion

		#region LeftClickCommandParameter dependency property

		/// <summary>
		/// Command parameter for the <see cref="LeftClickCommand"/>.
		/// </summary>
		static public readonly DependencyProperty LeftClickCommandParameterProperty =
			DependencyProperty.Register("LeftClickCommandParameter",
			                            typeof(object),
			                            typeof(TaskbarIcon),
			                            new FrameworkPropertyMetadata(null));

		/// <summary>
		/// A property wrapper for the <see cref="LeftClickCommandParameterProperty"/>
		/// dependency property:<br/>
		/// Command parameter for the <see cref="LeftClickCommand"/>.
		/// </summary>
		public object LeftClickCommandParameter
		{
			get { return this.GetValue(LeftClickCommandParameterProperty); }
			set { this.SetValue(LeftClickCommandParameterProperty, value); }
		}

		#endregion

		#region LeftClickCommandTarget dependency property

		/// <summary>
		/// The target of the command that is fired if the notify icon is clicked.
		/// </summary>
		static public readonly DependencyProperty LeftClickCommandTargetProperty =
			DependencyProperty.Register("LeftClickCommandTarget",
			                            typeof(IInputElement),
			                            typeof(TaskbarIcon),
			                            new FrameworkPropertyMetadata(null));

		/// <summary>
		/// A property wrapper for the <see cref="LeftClickCommandTargetProperty"/>
		/// dependency property:<br/>
		/// The target of the command that is fired if the notify icon is clicked.
		/// </summary>
		public IInputElement LeftClickCommandTarget
		{
			get { return (IInputElement)this.GetValue(LeftClickCommandTargetProperty); }
			set { this.SetValue(LeftClickCommandTargetProperty, value); }
		}

		#endregion

		#region TrayLeftMouseDown

		/// <summary>
		/// TrayLeftMouseDown Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayLeftMouseDownEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseDown",
		                                                                                             RoutingStrategy.Bubble,
		                                                                                             typeof(RoutedEventHandler
		                                                                                             	),
		                                                                                             typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the user presses the left mouse button.
		/// </summary>
		[Category(CategoryName)]
		public event RoutedEventHandler TrayLeftMouseDown
		{
			add { this.AddHandler(TrayLeftMouseDownEvent, value); }
			remove { this.RemoveHandler(TrayLeftMouseDownEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayLeftMouseDown event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayLeftMouseDownEvent()
		{
			RoutedEventArgs args = RaiseTrayLeftMouseDownEvent(this);
			return args;
		}

		/// <summary>
		/// A static helper method to raise the TrayLeftMouseDown event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayLeftMouseDownEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayLeftMouseDownEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayRightMouseDown

		/// <summary>
		/// TrayRightMouseDown Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayRightMouseDownEvent = EventManager.RegisterRoutedEvent("TrayRightMouseDown",
		                                                                                              RoutingStrategy.Bubble,
		                                                                                              typeof(
		                                                                                              	RoutedEventHandler),
		                                                                                              typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the presses the right mouse button.
		/// </summary>
		public event RoutedEventHandler TrayRightMouseDown
		{
			add { this.AddHandler(TrayRightMouseDownEvent, value); }
			remove { this.RemoveHandler(TrayRightMouseDownEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayRightMouseDown event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayRightMouseDownEvent()
		{
			return RaiseTrayRightMouseDownEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayRightMouseDown event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayRightMouseDownEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayRightMouseDownEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayMiddleMouseDown

		/// <summary>
		/// TrayMiddleMouseDown Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayMiddleMouseDownEvent = EventManager.RegisterRoutedEvent("TrayMiddleMouseDown",
		                                                                                               RoutingStrategy.Bubble,
		                                                                                               typeof(
		                                                                                               	RoutedEventHandler),
		                                                                                               typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the user presses the middle mouse button.
		/// </summary>
		public event RoutedEventHandler TrayMiddleMouseDown
		{
			add { this.AddHandler(TrayMiddleMouseDownEvent, value); }
			remove { this.RemoveHandler(TrayMiddleMouseDownEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayMiddleMouseDown event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayMiddleMouseDownEvent()
		{
			return RaiseTrayMiddleMouseDownEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayMiddleMouseDown event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayMiddleMouseDownEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayMiddleMouseDownEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayLeftMouseUp

		/// <summary>
		/// TrayLeftMouseUp Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayLeftMouseUpEvent = EventManager.RegisterRoutedEvent("TrayLeftMouseUp",
		                                                                                           RoutingStrategy.Bubble,
		                                                                                           typeof(RoutedEventHandler),
		                                                                                           typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the user releases the left mouse button.
		/// </summary>
		public event RoutedEventHandler TrayLeftMouseUp
		{
			add { this.AddHandler(TrayLeftMouseUpEvent, value); }
			remove { this.RemoveHandler(TrayLeftMouseUpEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayLeftMouseUp event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayLeftMouseUpEvent()
		{
			return RaiseTrayLeftMouseUpEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayLeftMouseUp event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayLeftMouseUpEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayLeftMouseUpEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayRightMouseUp

		/// <summary>
		/// TrayRightMouseUp Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayRightMouseUpEvent = EventManager.RegisterRoutedEvent("TrayRightMouseUp",
		                                                                                            RoutingStrategy.Bubble,
		                                                                                            typeof(RoutedEventHandler),
		                                                                                            typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the user releases the right mouse button.
		/// </summary>
		public event RoutedEventHandler TrayRightMouseUp
		{
			add { this.AddHandler(TrayRightMouseUpEvent, value); }
			remove { this.RemoveHandler(TrayRightMouseUpEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayRightMouseUp event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayRightMouseUpEvent()
		{
			return RaiseTrayRightMouseUpEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayRightMouseUp event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayRightMouseUpEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayRightMouseUpEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayMiddleMouseUp

		/// <summary>
		/// TrayMiddleMouseUp Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayMiddleMouseUpEvent = EventManager.RegisterRoutedEvent("TrayMiddleMouseUp",
		                                                                                             RoutingStrategy.Bubble,
		                                                                                             typeof(RoutedEventHandler
		                                                                                             	),
		                                                                                             typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the user releases the middle mouse button.
		/// </summary>
		public event RoutedEventHandler TrayMiddleMouseUp
		{
			add { this.AddHandler(TrayMiddleMouseUpEvent, value); }
			remove { this.RemoveHandler(TrayMiddleMouseUpEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayMiddleMouseUp event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayMiddleMouseUpEvent()
		{
			return RaiseTrayMiddleMouseUpEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayMiddleMouseUp event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayMiddleMouseUpEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayMiddleMouseUpEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayMouseDoubleClick

		/// <summary>
		/// TrayMouseDoubleClick Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayMouseDoubleClickEvent = EventManager.RegisterRoutedEvent(
		                                                                                                "TrayMouseDoubleClick",
		                                                                                                RoutingStrategy.Bubble,
		                                                                                                typeof(
		                                                                                                	RoutedEventHandler),
		                                                                                                typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the user double-clicks the taskbar icon.
		/// </summary>
		public event RoutedEventHandler TrayMouseDoubleClick
		{
			add { this.AddHandler(TrayMouseDoubleClickEvent, value); }
			remove { this.RemoveHandler(TrayMouseDoubleClickEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayMouseDoubleClick event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayMouseDoubleClickEvent()
		{
			RoutedEventArgs args = RaiseTrayMouseDoubleClickEvent(this);
			this.DoubleClickCommand.ExecuteIfEnabled(this.DoubleClickCommandParameter, this.DoubleClickCommandTarget ?? this);
			return args;
		}

		/// <summary>
		/// A static helper method to raise the TrayMouseDoubleClick event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayMouseDoubleClickEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayMouseDoubleClickEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayMouseMove

		/// <summary>
		/// TrayMouseMove Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayMouseMoveEvent = EventManager.RegisterRoutedEvent("TrayMouseMove",
		                                                                                         RoutingStrategy.Bubble,
		                                                                                         typeof(RoutedEventHandler),
		                                                                                         typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the user moves the mouse over the taskbar icon.
		/// </summary>
		public event RoutedEventHandler TrayMouseMove
		{
			add { this.AddHandler(TrayMouseMoveEvent, value); }
			remove { this.RemoveHandler(TrayMouseMoveEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayMouseMove event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayMouseMoveEvent()
		{
			return RaiseTrayMouseMoveEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayMouseMove event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayMouseMoveEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayMouseMoveEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayBalloonTipShown

		/// <summary>
		/// TrayBalloonTipShown Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayBalloonTipShownEvent = EventManager.RegisterRoutedEvent("TrayBalloonTipShown",
		                                                                                               RoutingStrategy.Bubble,
		                                                                                               typeof(
		                                                                                               	RoutedEventHandler),
		                                                                                               typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when a balloon ToolTip is displayed.
		/// </summary>
		public event RoutedEventHandler TrayBalloonTipShown
		{
			add { this.AddHandler(TrayBalloonTipShownEvent, value); }
			remove { this.RemoveHandler(TrayBalloonTipShownEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayBalloonTipShown event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayBalloonTipShownEvent()
		{
			return RaiseTrayBalloonTipShownEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayBalloonTipShown event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayBalloonTipShownEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayBalloonTipShownEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayBalloonTipClosed

		/// <summary>
		/// TrayBalloonTipClosed Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayBalloonTipClosedEvent = EventManager.RegisterRoutedEvent(
		                                                                                                "TrayBalloonTipClosed",
		                                                                                                RoutingStrategy.Bubble,
		                                                                                                typeof(
		                                                                                                	RoutedEventHandler),
		                                                                                                typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when a balloon ToolTip was closed.
		/// </summary>
		public event RoutedEventHandler TrayBalloonTipClosed
		{
			add { this.AddHandler(TrayBalloonTipClosedEvent, value); }
			remove { this.RemoveHandler(TrayBalloonTipClosedEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayBalloonTipClosed event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayBalloonTipClosedEvent()
		{
			return RaiseTrayBalloonTipClosedEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayBalloonTipClosed event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayBalloonTipClosedEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayBalloonTipClosedEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayBalloonTipClicked

		/// <summary>
		/// TrayBalloonTipClicked Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayBalloonTipClickedEvent =
			EventManager.RegisterRoutedEvent("TrayBalloonTipClicked",
			                                 RoutingStrategy.Bubble,
			                                 typeof(RoutedEventHandler),
			                                 typeof(TaskbarIcon));

		/// <summary>
		/// Occurs when the user clicks on a balloon ToolTip.
		/// </summary>
		public event RoutedEventHandler TrayBalloonTipClicked
		{
			add { this.AddHandler(TrayBalloonTipClickedEvent, value); }
			remove { this.RemoveHandler(TrayBalloonTipClickedEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayBalloonTipClicked event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayBalloonTipClickedEvent()
		{
			return RaiseTrayBalloonTipClickedEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayBalloonTipClicked event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayBalloonTipClickedEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayBalloonTipClickedEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayContextMenuOpen (and PreviewTrayContextMenuOpen)

		/// <summary>
		/// TrayContextMenuOpen Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayContextMenuOpenEvent = EventManager.RegisterRoutedEvent("TrayContextMenuOpen",
		                                                                                               RoutingStrategy.Bubble,
		                                                                                               typeof(
		                                                                                               	RoutedEventHandler),
		                                                                                               typeof(TaskbarIcon));

		/// <summary>
		/// PreviewTrayContextMenuOpen Routed Event
		/// </summary>
		static public readonly RoutedEvent PreviewTrayContextMenuOpenEvent =
			EventManager.RegisterRoutedEvent("PreviewTrayContextMenuOpen",
			                                 RoutingStrategy.Tunnel,
			                                 typeof(RoutedEventHandler),
			                                 typeof(TaskbarIcon));

		/// <summary>
		/// Bubbled event that occurs when the context menu of the taskbar icon is being displayed.
		/// </summary>
		public event RoutedEventHandler TrayContextMenuOpen
		{
			add { this.AddHandler(TrayContextMenuOpenEvent, value); }
			remove { this.RemoveHandler(TrayContextMenuOpenEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayContextMenuOpen event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayContextMenuOpenEvent()
		{
			return RaiseTrayContextMenuOpenEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayContextMenuOpen event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayContextMenuOpenEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayContextMenuOpenEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		/// <summary>
		/// Tunneled event that occurs when the context menu of the taskbar icon is being displayed.
		/// </summary>
		public event RoutedEventHandler PreviewTrayContextMenuOpen
		{
			add { this.AddHandler(PreviewTrayContextMenuOpenEvent, value); }
			remove { this.RemoveHandler(PreviewTrayContextMenuOpenEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the PreviewTrayContextMenuOpen event.
		/// </summary>
		protected RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent()
		{
			return RaisePreviewTrayContextMenuOpenEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the PreviewTrayContextMenuOpen event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaisePreviewTrayContextMenuOpenEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = PreviewTrayContextMenuOpenEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayPopupOpen (and PreviewTrayPopupOpen)

		/// <summary>
		/// TrayPopupOpen Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayPopupOpenEvent = EventManager.RegisterRoutedEvent("TrayPopupOpen",
		                                                                                         RoutingStrategy.Bubble,
		                                                                                         typeof(RoutedEventHandler),
		                                                                                         typeof(TaskbarIcon));

		/// <summary>
		/// PreviewTrayPopupOpen Routed Event
		/// </summary>
		static public readonly RoutedEvent PreviewTrayPopupOpenEvent = EventManager.RegisterRoutedEvent(
		                                                                                                "PreviewTrayPopupOpen",
		                                                                                                RoutingStrategy.Tunnel,
		                                                                                                typeof(
		                                                                                                	RoutedEventHandler),
		                                                                                                typeof(TaskbarIcon));

		/// <summary>
		/// Bubbled event that occurs when the custom popup is being opened.
		/// </summary>
		public event RoutedEventHandler TrayPopupOpen
		{
			add { this.AddHandler(TrayPopupOpenEvent, value); }
			remove { this.RemoveHandler(TrayPopupOpenEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayPopupOpen event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayPopupOpenEvent()
		{
			return RaiseTrayPopupOpenEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayPopupOpen event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayPopupOpenEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayPopupOpenEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		/// <summary>
		/// Tunneled event that occurs when the custom popup is being opened.
		/// </summary>
		public event RoutedEventHandler PreviewTrayPopupOpen
		{
			add { this.AddHandler(PreviewTrayPopupOpenEvent, value); }
			remove { this.RemoveHandler(PreviewTrayPopupOpenEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the PreviewTrayPopupOpen event.
		/// </summary>
		protected RoutedEventArgs RaisePreviewTrayPopupOpenEvent()
		{
			return RaisePreviewTrayPopupOpenEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the PreviewTrayPopupOpen event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaisePreviewTrayPopupOpenEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = PreviewTrayPopupOpenEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayToolTipOpen (and PreviewTrayToolTipOpen)

		/// <summary>
		/// TrayToolTipOpen Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayToolTipOpenEvent = EventManager.RegisterRoutedEvent("TrayToolTipOpen",
		                                                                                           RoutingStrategy.Bubble,
		                                                                                           typeof(RoutedEventHandler),
		                                                                                           typeof(TaskbarIcon));

		/// <summary>
		/// PreviewTrayToolTipOpen Routed Event
		/// </summary>
		static public readonly RoutedEvent PreviewTrayToolTipOpenEvent =
			EventManager.RegisterRoutedEvent("PreviewTrayToolTipOpen",
			                                 RoutingStrategy.Tunnel,
			                                 typeof(RoutedEventHandler),
			                                 typeof(TaskbarIcon));

		/// <summary>
		/// Bubbled event that occurs when the custom ToolTip is being displayed.
		/// </summary>
		public event RoutedEventHandler TrayToolTipOpen
		{
			add { this.AddHandler(TrayToolTipOpenEvent, value); }
			remove { this.RemoveHandler(TrayToolTipOpenEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayToolTipOpen event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayToolTipOpenEvent()
		{
			return RaiseTrayToolTipOpenEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayToolTipOpen event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayToolTipOpenEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayToolTipOpenEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		/// <summary>
		/// Tunneled event that occurs when the custom ToolTip is being displayed.
		/// </summary>
		public event RoutedEventHandler PreviewTrayToolTipOpen
		{
			add { this.AddHandler(PreviewTrayToolTipOpenEvent, value); }
			remove { this.RemoveHandler(PreviewTrayToolTipOpenEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the PreviewTrayToolTipOpen event.
		/// </summary>
		protected RoutedEventArgs RaisePreviewTrayToolTipOpenEvent()
		{
			return RaisePreviewTrayToolTipOpenEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the PreviewTrayToolTipOpen event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaisePreviewTrayToolTipOpenEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = PreviewTrayToolTipOpenEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region TrayToolTipClose (and PreviewTrayToolTipClose)

		/// <summary>
		/// TrayToolTipClose Routed Event
		/// </summary>
		static public readonly RoutedEvent TrayToolTipCloseEvent = EventManager.RegisterRoutedEvent("TrayToolTipClose",
		                                                                                            RoutingStrategy.Bubble,
		                                                                                            typeof(RoutedEventHandler),
		                                                                                            typeof(TaskbarIcon));

		/// <summary>
		/// PreviewTrayToolTipClose Routed Event
		/// </summary>
		static public readonly RoutedEvent PreviewTrayToolTipCloseEvent =
			EventManager.RegisterRoutedEvent("PreviewTrayToolTipClose",
			                                 RoutingStrategy.Tunnel,
			                                 typeof(RoutedEventHandler),
			                                 typeof(TaskbarIcon));

		/// <summary>
		/// Bubbled event that occurs when a custom tooltip is being closed.
		/// </summary>
		public event RoutedEventHandler TrayToolTipClose
		{
			add { this.AddHandler(TrayToolTipCloseEvent, value); }
			remove { this.RemoveHandler(TrayToolTipCloseEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the TrayToolTipClose event.
		/// </summary>
		protected RoutedEventArgs RaiseTrayToolTipCloseEvent()
		{
			return RaiseTrayToolTipCloseEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the TrayToolTipClose event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseTrayToolTipCloseEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = TrayToolTipCloseEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		/// <summary>
		/// Tunneled event that occurs when a custom tooltip is being closed.
		/// </summary>
		public event RoutedEventHandler PreviewTrayToolTipClose
		{
			add { this.AddHandler(PreviewTrayToolTipCloseEvent, value); }
			remove { this.RemoveHandler(PreviewTrayToolTipCloseEvent, value); }
		}

		/// <summary>
		/// A helper method to raise the PreviewTrayToolTipClose event.
		/// </summary>
		protected RoutedEventArgs RaisePreviewTrayToolTipCloseEvent()
		{
			return RaisePreviewTrayToolTipCloseEvent(this);
		}

		/// <summary>
		/// A static helper method to raise the PreviewTrayToolTipClose event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaisePreviewTrayToolTipCloseEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = PreviewTrayToolTipCloseEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region PopupOpened

		/// <summary>
		/// PopupOpened Attached Routed Event
		/// </summary>
		static public readonly RoutedEvent PopupOpenedEvent = EventManager.RegisterRoutedEvent("PopupOpened",
		                                                                                       RoutingStrategy.Bubble,
		                                                                                       typeof(RoutedEventHandler),
		                                                                                       typeof(TaskbarIcon));

		/// <summary>
		/// Adds a handler for the PopupOpened attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be added</param>
		static public void AddPopupOpenedHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.AddHandler(element, PopupOpenedEvent, handler);
		}

		/// <summary>
		/// Removes a handler for the PopupOpened attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be removed</param>
		static public void RemovePopupOpenedHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.RemoveHandler(element, PopupOpenedEvent, handler);
		}

		/// <summary>
		/// A static helper method to raise the PopupOpened event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaisePopupOpenedEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = PopupOpenedEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region ToolTipOpened

		/// <summary>
		/// ToolTipOpened Attached Routed Event
		/// </summary>
		static public readonly RoutedEvent ToolTipOpenedEvent = EventManager.RegisterRoutedEvent("ToolTipOpened",
		                                                                                         RoutingStrategy.Bubble,
		                                                                                         typeof(RoutedEventHandler),
		                                                                                         typeof(TaskbarIcon));

		/// <summary>
		/// Adds a handler for the ToolTipOpened attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be added</param>
		static public void AddToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.AddHandler(element, ToolTipOpenedEvent, handler);
		}

		/// <summary>
		/// Removes a handler for the ToolTipOpened attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be removed</param>
		static public void RemoveToolTipOpenedHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.RemoveHandler(element, ToolTipOpenedEvent, handler);
		}

		/// <summary>
		/// A static helper method to raise the ToolTipOpened event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseToolTipOpenedEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = ToolTipOpenedEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region ToolTipClose

		/// <summary>
		/// ToolTipClose Attached Routed Event
		/// </summary>
		static public readonly RoutedEvent ToolTipCloseEvent = EventManager.RegisterRoutedEvent("ToolTipClose",
		                                                                                        RoutingStrategy.Bubble,
		                                                                                        typeof(RoutedEventHandler),
		                                                                                        typeof(TaskbarIcon));

		/// <summary>
		/// Adds a handler for the ToolTipClose attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be added</param>
		static public void AddToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.AddHandler(element, ToolTipCloseEvent, handler);
		}

		/// <summary>
		/// Removes a handler for the ToolTipClose attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be removed</param>
		static public void RemoveToolTipCloseHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.RemoveHandler(element, ToolTipCloseEvent, handler);
		}

		/// <summary>
		/// A static helper method to raise the ToolTipClose event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		static internal RoutedEventArgs RaiseToolTipCloseEvent(DependencyObject target)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs();
			args.RoutedEvent = ToolTipCloseEvent;
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region BalloonShowing

		/// <summary>
		/// BalloonShowing Attached Routed Event
		/// </summary>
		static public readonly RoutedEvent BalloonShowingEvent = EventManager.RegisterRoutedEvent("BalloonShowing",
		                                                                                          RoutingStrategy.Bubble,
		                                                                                          typeof(RoutedEventHandler),
		                                                                                          typeof(TaskbarIcon));

		/// <summary>
		/// Adds a handler for the BalloonShowing attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be added</param>
		static public void AddBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.AddHandler(element, BalloonShowingEvent, handler);
		}

		/// <summary>
		/// Removes a handler for the BalloonShowing attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be removed</param>
		static public void RemoveBalloonShowingHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.RemoveHandler(element, BalloonShowingEvent, handler);
		}

		/// <summary>
		/// A static helper method to raise the BalloonShowing event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		/// <param name="source">The <see cref="TaskbarIcon"/> instance that manages the balloon.</param>
		static internal RoutedEventArgs RaiseBalloonShowingEvent(DependencyObject target, TaskbarIcon source)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs(BalloonShowingEvent, source);
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region BalloonClosing

		/// <summary>
		/// BalloonClosing Attached Routed Event
		/// </summary>
		static public readonly RoutedEvent BalloonClosingEvent = EventManager.RegisterRoutedEvent("BalloonClosing",
		                                                                                          RoutingStrategy.Bubble,
		                                                                                          typeof(RoutedEventHandler),
		                                                                                          typeof(TaskbarIcon));

		/// <summary>
		/// Adds a handler for the BalloonClosing attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be added</param>
		static public void AddBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.AddHandler(element, BalloonClosingEvent, handler);
		}

		/// <summary>
		/// Removes a handler for the BalloonClosing attached event
		/// </summary>
		/// <param name="element">UIElement or ContentElement that listens to the event</param>
		/// <param name="handler">Event handler to be removed</param>
		static public void RemoveBalloonClosingHandler(DependencyObject element, RoutedEventHandler handler)
		{
			RoutedEventHelper.RemoveHandler(element, BalloonClosingEvent, handler);
		}

		/// <summary>
		/// A static helper method to raise the BalloonClosing event on a target element.
		/// </summary>
		/// <param name="target">UIElement or ContentElement on which to raise the event</param>
		/// <param name="source">The <see cref="TaskbarIcon"/> instance that manages the balloon.</param>
		static internal RoutedEventArgs RaiseBalloonClosingEvent(DependencyObject target, TaskbarIcon source)
		{
			if (target == null)
				return null;

			RoutedEventArgs args = new RoutedEventArgs(BalloonClosingEvent, source);
			RoutedEventHelper.RaiseEvent(target, args);
			return args;
		}

		#endregion

		#region ParentTaskbarIcon

		/// <summary>
		/// An attached property that is assigned to 
		/// </summary>  
		static public readonly DependencyProperty ParentTaskbarIconProperty =
			DependencyProperty.RegisterAttached("ParentTaskbarIcon", typeof(TaskbarIcon), typeof(TaskbarIcon));

		/// <summary>
		/// Gets the ParentTaskbarIcon property.  This dependency property 
		/// indicates ....
		/// </summary>
		static public TaskbarIcon GetParentTaskbarIcon(DependencyObject d)
		{
			return (TaskbarIcon)d.GetValue(ParentTaskbarIconProperty);
		}

		/// <summary>
		/// Sets the ParentTaskbarIcon property.  This dependency property 
		/// indicates ....
		/// </summary>
		static public void SetParentTaskbarIcon(DependencyObject d, TaskbarIcon value)
		{
			d.SetValue(ParentTaskbarIconProperty, value);
		}

		#endregion

		//POPUP CONTROLS

		//DEPENDENCY PROPERTIES

		//EVENTS

		//ATTACHED EVENTS

		//ATTACHED PROPERTIES

		//BASE CLASS PROPERTY OVERRIDES

		/// <summary>
		/// Registers properties.
		/// </summary>
		static TaskbarIcon()
		{
			//register change listener for the Visibility property
			PropertyMetadata md = new PropertyMetadata(Visibility.Visible, VisibilityPropertyChanged);
			VisibilityProperty.OverrideMetadata(typeof(TaskbarIcon), md);

			//register change listener for the DataContext property
			md = new FrameworkPropertyMetadata(new PropertyChangedCallback(DataContextPropertyChanged));
			DataContextProperty.OverrideMetadata(typeof(TaskbarIcon), md);

			//register change listener for the ContextMenu property
			md = new FrameworkPropertyMetadata(new PropertyChangedCallback(ContextMenuPropertyChanged));
			ContextMenuProperty.OverrideMetadata(typeof(TaskbarIcon), md);
		}
	}
}